﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ExcellData;
using Microsoft.Win32;

namespace ExcelUtilitiesFactory
{
	public class ExcelFactory
	{
		public static IExcelIntegration CreateExcelIntegration()
		{
			EOfficeVersion currentVersion = GetOfficeVersion(EOfficeApplication.Excel);

			switch (currentVersion)
			{
				case EOfficeVersion.Office_95:
				case EOfficeVersion.Office_97:
				case EOfficeVersion.Office_2000:
				case EOfficeVersion.Office_XP:
				case EOfficeVersion.Office_2003:
					return ExcelUtilities11.ExcelIntegration.Instance;
				case EOfficeVersion.Office_2007:
					return ExcelUtilities12.ExcelIntegration.Instance;
				case EOfficeVersion.Office_2010:
					return ExcelUtilities14.ExcelIntegration.Instance;
				case EOfficeVersion.Unknown:
				default:
					throw new NotSupportedException("É necessário ter uma versão do office instalada neste computador para utilizar esta função");
			}
		}

		private enum EOfficeVersion
		{
			Unknown, // error return value
			Office_95	= 7,
			Office_97	= 8,
			Office_2000	= 9,
			Office_XP	= 10,
			Office_2003	= 11,
			Office_2007	= 12,
			Office_2010	= 14,
		}

		private enum EOfficeApplication
		{
			Word,
			Excel,
			Outlook,
			Access,
			PowerPoint,
		}

		private static EOfficeVersion GetOfficeVersion(EOfficeApplication appToCheck)
		{
			string progID = GetProgID(appToCheck);

			RegistryKey hKey = Registry.ClassesRoot.OpenSubKey(progID, RegistryKeyPermissionCheck.ReadSubTree, System.Security.AccessControl.RegistryRights.ReadKey);
			if (hKey == null)
				return EOfficeVersion.Unknown;

			RegistryKey hKey1 = hKey.OpenSubKey("CurVer", RegistryKeyPermissionCheck.ReadSubTree, System.Security.AccessControl.RegistryRights.ReadKey);
			if (hKey1 == null)
			{
				hKey1.Close();
				hKey.Close();
				return EOfficeVersion.Unknown;
			}

			// Get the Version information
			string progAndVersion = (string)hKey1.GetValue("");

			// Close the registry keys
			hKey1.Close();
			hKey.Close();

			// Error while querying for value
			if (progAndVersion == null)
				return EOfficeVersion.Unknown;

			// At this point progAndVersion contains the ProgID followed by a number. 
			// For example, Word 97 will return Word.Application.8 and Word 2000 will return Word.Application.9

			int lastDot = progAndVersion.LastIndexOf('.');
			int firstCharOfVersion = lastDot + 1; // + 1 to get rid of the dot at the front
			string versionString = progAndVersion.Substring(firstCharOfVersion, progAndVersion.Length - firstCharOfVersion);

			return StringToVersion(versionString);
		}

		private static string GetApplicationAsString(EOfficeApplication officeApp)
		{
			switch (officeApp)
			{
				case EOfficeApplication.Word:
					return "Word";
				case EOfficeApplication.Excel:
					return "Excel";
				case EOfficeApplication.Outlook:
					return "Outlook";
				case EOfficeApplication.Access:
					return "Access";
				case EOfficeApplication.PowerPoint:
					return "Powerpoint";
				default:
					return string.Empty;
			}
		}

		private static string GetProgID(EOfficeApplication officeApp)
		{
			// ProgIDs from http://support.microsoft.com/kb/240794/EN-US/
			switch (officeApp)
			{
				case EOfficeApplication.Word:
					return "Word.Application";
				case EOfficeApplication.Excel: 
					return "Excel.Application";
				case EOfficeApplication.Outlook: 
					return "Outlook.Application";
				case EOfficeApplication.Access:
					return "Access.Application"; 
				case EOfficeApplication.PowerPoint:
					return "Powerpoint.Application";
				default: 
					return string.Empty;
			}
		}

		private static EOfficeVersion StringToVersion(string versionString)
		{
			try
			{
				// Tenta converter pra um valor equivalente, caso não consiga, retorna Unknown
				return (EOfficeVersion)int.Parse(versionString);
			}
			catch (Exception)
			{
				return EOfficeVersion.Unknown;
			}
		}
	}
}
